package cc.eddic.practice.spring.webapi;

import cc.eddic.practice.spring.domain.SubCategory;
import cc.eddic.practice.spring.dto.CategoryAddRequest;
import cc.eddic.practice.spring.dto.CategoryResponse;
import cc.eddic.practice.spring.dto.SubCategoryAddRequest;
import cc.eddic.practice.spring.dto.SubCategoryResponse;
import cc.eddic.practice.spring.repository.CategoryRepository;
import cc.eddic.practice.spring.repository.SubCategoryRepository;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.http.HttpEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import javax.transaction.Transactional;
import java.util.Comparator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/api/categorys")
public class CategoryController {
    public CategoryController(CategoryRepository repository) {
        this.repository = repository;
    }

    @PostMapping
    public HttpEntity<?> add(@RequestBody final CategoryAddRequest model) {
        val category = repository.save(model.as());
        return ResponseEntity.created(ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}").buildAndExpand(category.getId()).toUri()).build();
    }

    @GetMapping("/{id}")
    public HttpEntity<CategoryResponse> get(@PathVariable("id") final long id) {
        if (log.isDebugEnabled()) log.debug("id={}", id);
        val category = repository.findById(id).orElseThrow(NoSuchElementException::new);
        return ResponseEntity.ok(CategoryResponse.from(category));
    }

    @Transactional
    @PostMapping("/{categoryId}/subcategorys")
    public HttpEntity<?> add(@PathVariable("categoryId") Long categoryId, @RequestBody final SubCategoryAddRequest model) {
        val category = repository.findById(categoryId).orElseThrow(NoSuchElementException::new);
        val subCategory = model.as();
        category.add(subCategory);
        repository.save(category);

        val id = category.getSubCategorys().stream()
                .filter(x -> x.getName().equals(model.getName()))
                .sorted(Comparator.comparing(SubCategory::getCreatedOn).reversed())
                .map(SubCategory::getId)
                .findFirst().orElse(-1L);
        //return ResponseEntity.created(ServletUriComponentsBuilder.fromCurrentRequest().path("/{categoryId}/subcategorys/{subCategoryId}").buildAndExpand(subCategory.getId()).toUri()).build();
        return ResponseEntity.created(ServletUriComponentsBuilder.fromCurrentRequest().path("/{subCategoryId}")
                .buildAndExpand(subCategory.getId(), id).toUri()).build();
    }

    @GetMapping("/{categoryId}/subcategorys")
    public HttpEntity<?> get(@PathVariable("categoryId") Long categoryId) {
        if (log.isDebugEnabled()) log.debug("categoryId ={}", categoryId);
        val category = repository.findById(categoryId).orElseThrow(NoSuchElementException::new);
        return ResponseEntity.ok(category.getSubCategorys().stream().map(SubCategoryResponse::from).collect(Collectors.toList()));

    }

    @GetMapping("/{categoryId}/subcategorys/{subCategoryId}")
    public HttpEntity<?> get(@PathVariable("categoryId") Long categoryId, @PathVariable("subCategoryId") Long subCategoryId) {
        if (log.isDebugEnabled()) log.debug("categoryId ={}", categoryId);
        val category = repository.findById(categoryId).orElseThrow(NoSuchElementException::new);
        val subcategory = category.getSubCategorys().stream().filter(subCategory -> subCategory.getId().equals(subCategoryId)).findFirst().orElseThrow(NoSuchElementException::new);
        return ResponseEntity.ok(SubCategoryResponse.from(subcategory));

    }


    @DeleteMapping("/{id}")
    public HttpEntity<?> del(@PathVariable("id") final long id) {
        repository.deleteById(id);
        return ResponseEntity.noContent().build();
    }

    @GetMapping
    public HttpEntity<List<CategoryResponse>> getAll() {
        val categorys = repository.findAll().stream().map(CategoryResponse::from).collect(Collectors.toList());
        return ResponseEntity.ok(categorys);
    }


    private final CategoryRepository repository;


}
